/*! \file guiclass.h	
	This is the header file for guiclass.cpp
	
	This contains the GUI class. gui.h and gui.cpp should not exist.
	
	Something to note about this class:
	1. It is a singleton
	2. draw() is done in reverse order on the list of components, so the first component
		in the list is drawn last. The first component in the list also gets all the events (mouse/key input)
		first, so this is like z-ordering containers.
*/

#ifndef GUICLASS_H
#define GUICLASS_H

#include <list>
#include <iostream>
#include "component.h"
#include "guiconstants.h"
#include "font.h"
#include "hovertext.h"
using namespace std;

/**
	\class GUI

	This keeps track of the top-level containers.
*/

class GUI : public Component {
private:
	// Statics are initialized in the .cpp file!
	static GUI* gui;
	static Font* font;
	/**
	* This is the container that has the focus, so that when you hit tab,
	* it doesn't change to a text field in another window (like the chat bar)
	*
	* This focus can be changed by clicking a new container.
	*/
	Component* focusedComponent;

	/**
	* If the lockedComponent is not null, then all mouse events will go to this.
	* This is so that dragging a scrollbar around will still work outside of the parent it belongs to,
	* but prevents anything else from being accessed while that is going on.
	*
	* See "setLockedComponent" for additional information.
	*/
	Container* lockedComponent;

	/**
	* Private constructor because this is a singleton class
	* It sets its own position to 0, it has no parent, and it initializes the font here.
	*/
	GUI();
	
	/**
	* This list keeps track of the top-level containers. These are defined as
	* containers with the GUI as a parent (not another container).
	* These are arranged in Z-order. I.e. the first component in this
	* list will be drawn last and will get the input, because it has the focus.
	*/
	list<Component*> allContainers;
	
	
	static int nextGuiId; //!< this is probably unused
	
public:

	/**
	* This returns the instance of the GUI (singleton class)
	*/
	static GUI* getInstance();
	
	/**
	* This should be unused
	*/
	static int nextAvailableID();
	
	
	static bool rShiftHeld; //!< This is true if right-shift is held
	static bool lShiftHeld; //!< This is true if left-shift is held
	static bool rCtrlHeld; //!< This is true if right-ctrl is held
	static bool lCtrlHeld; //!< This is true if left-ctrl is held
	static bool lMouseHeld;

	/**
	* This returns true if either right-shift or left-shift is held
	*/
	static bool shiftHeld();
	
	/**
	* This returns true if either right-ctrl or left-ctrl is held
	*/
	static bool ctrlHeld();
	
	static void setClippingArea( int x, int y, int w, int h );
	
	static void removeClippingArea();
	
	/**
	* This draws a gradient rectangle (gradient goes from top to bottom) using GL_QUADS
	* THIS IS DEPRECATED!
	* \param x		the screen coordinate of the left side
	* \param y		the screen coordinate of the top side
	* \param w		the width of the rectangle
	* \param h		the height of the rectangle
	* \param r1		red value of top of gradient
	* \param g1		green value of top of gradient
	* \param b1		blue value of top of gradient
	* \param r2		red value of bottom of gradient
	* \param g2		green value of bottom of gradient
	* \param b2		blue value of bottom of gradient
	*/
	static void drawRectangle( int x, int y, int w, int h, float r1, float g1, float b1, float r2, float g2, float b2 );

	/**
	* This draws a gradient rectangle using GL_QUADS.
	*
	* \param x			the screen coordinate of the left side
	* \param y			the screen coordinate of the top side
	* \param w			the width of the rectangle
	* \param h			the height of the rectangle
	* \param lowColor	if the orientation is vertical, then this is the topColor (of the gradient), otherwise it's the leftColor
	* \param highColor	if the orientation is vertical, then this is the bottomColor, otherwise it's the rightColor
	* \param vertical	Whether the gradient should be vertical or not
	*/
	static void drawRectangle( int x, int y, int w, int h, Color& lowColor, Color& highColor, bool vertical = true );
	
	static void drawRectangle( int w, int h, Color& lowColor, Color& highColor, bool vertical = true );

	
	/**
	* This returns which component has the focus. This will [probably] always represent
	* a Container, but a Container is a Component anyway.
	*/
	Component* getFocusedComponent();
	
	/**
	* This sets which component has the focus. This will [probably] always represent
	* a Container.
	* If it is a container (and it should be), then this will move the container
	* to the front of the allContainers list, making its Z-order the highest, meaning
	* it will be moved to the front visually.
	*/
	void setFocusedComponent( Component* c );
	
	/**
	* This sets which component has the lock. The locked component will be the only component
	* to get mouse events, but it is different from the focus in that it does not have to be the component
	* on top. This is useful for mousing over something to produce hover-text, but then you might mouse off of
	* that but move directly onto another component, so it would never get the mouseLeave event as it normally would
	* from having moved the mouse off onto the parent container as opposed to a different component.
	*/
	void setLockedComponent( Container* c = 0 );
	
	/**
	* This just returns the currently locked component
	*/
	Container* getLockedComponent();
	
	/**
	* THIS IS CURRENTLY ONLY USED BY SCROLLBAR... when you have the mouse down over a button, it should
	* continue scrolling. However, this function would be used for animated GUI components too I suppose
	*/
	virtual void update();
		
	/**
	* This draws all of the children containers. It draws in reverse order to maintain the
	* Z-order.
	*/
	void draw();
		
	/**
	* This adds a component (probably must be a container) to the allContainers list
	*/
	void add( Component* c );
	
	/**
	* Returns whatever font is being used. This was initialized in the constructor of this class.
	*/
	Font* getFont() { return font; }
	
	/**
	* Probably unused
	*/
	virtual int getType();
	
	// The events get propagated from here to the containers, then from there to their
	// children if it applies.
	virtual bool handleMouseMove( int mX, int mY );
	virtual bool handleMouseWheel( int pos );
	virtual bool handleMouseClick( int button, int state );
	virtual void handleKeyInput( int key, int state );
		
};

#endif
